<?php
use GuzzleHttp\Client;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Promise;

/**
 * 异步批量Http请求服务类
 * @App	
 * @Group 
 * @Action HttpAsyncMutiRequestService
 * @author lilei
 * @date 2019年1月21日
 *
 */
namespace app\common\service;

use app\common\library\CommonFun;

class HttpAsyncMutiRequestService {
	/**
	 * HttpClient
	 * @var \GuzzleHttp\Client
	 */
	var $client;
	
	/**
	 * 基础Uri网关
	 * @var string
	 */
	var $base_uri;
	
	/**
	 * Request Option 配置
	 * @var array
	 */
	var $options = [];
	
	/**
	 * promise 列表
	 * @var array
	 */
	var $promise = [];
	
	/**
	 * 表示等待服务器响应超时的最大值，使用 0 将无限等待 (默认行为).
	 * @var int|float
	 */
	private $connect_timeout = 0;
	
	/**
	 * 请求超时的秒数。使用 0 无限期的等待(默认行为)。
	 * @var int|float
	 */
	private $timeout = 0;
	
	/**
	 * @var bool 是否允许重定向
	 */
	private $allow_redirects = true;
	
	/**
	 * Option属性列表
	 * @var array
	 */
	const optionList = ['base_uri','timeout','connect_timeout','allow_redirects'];
	
	/**
	 * Get请求方式
	 * @var string
	 */
	const methodGet = "GET";
	
	/**
	 * POST请求方式
	 * @var string
	 */
	const methodPost = "POST";
	
	/**
	 * 请求返回数据
	 * @var array
	 */
	var $results;
	
	/**
	 * 构造函数
	 * @param string $base_uri	基础Uri
	 */
	public function __construct( $base_uri='' ) {
		if ( $base_uri ) {
			// 基础Uri网关
			$this->base_uri = rtrim($base_uri, "/")."/";
		}
		
		// 设置Option
		if ( self::optionList ) {
			foreach ( self::optionList as $v ) {
				if ( isset( $this->{$v} ) ) {
					$this->setOptions( $v, $this->{$v} );
				}
			}
		}
		// 请求客户端
		$this->client = new Client( $this->options );
	}
	
	/**
	 * 返回单例模型
	 * @return static
	 */
	public static function getInstance() {
		$param = func_get_args ();
		return CommonFun::get_instance_of ( get_called_class (), '', $param );
	}
	
	/**
	 * 设置并发请求的Promise
	 * @param string	$resKey		返回数据获取标示
	 * @param string 	$uri		请求的URI部分或者URL
	 * @param array		$param		请求参数
	 * @param array 	$header		请求头文件
	 * @param string 	$method		请求方法
	 * @return $this
	 */
	public function setPromises( $resKey, $uri, array $param=[], array $header=[], $method="GET" ) {
		// 请求设置
		$request_opt = [];
		// 头信息
		if ( $header ) {
			$request_opt['headers'] = $header;
		}
		
		switch ( $method ) {
			case self::methodGet:
				if (!empty($param)) {
					$uri = $uri . '?' . http_build_query($param);
				}
				$this->promise[$resKey] = $this->client->getAsync($uri, $request_opt);
				break;
			case self::methodPost:
				if (!empty($param)) {
					$request_opt['form_params'] = $param;
				}
				$this->promise[$resKey] = $this->client->postAsync($uri, $request_opt);
				break;
		}
		return $this;
	}
	
	/**
	 * 启动请求
	 */
	public function runHttpAcyncMutiRequest() {
		if ( !$this->promise ) {
			return false;
		}
		try {
			$results = Promise\unwrap($this->promise);
		} catch (\Exception $e) {
			CommonFun::make_exception($e->getMessage());
			return false;
		}
		
		if ( !$results ) {
			return false;
		}
		foreach ( $results as $k=>&$v ) {
			$v = (string)$v->getBody();
		}
		return $this->results = $results;
	}
	
	/**
	 * 设置Request Option 配置
	 * @param mixed $name 配置名称
	 * @param mixed $value 配置值
	 * @return $this
	 */
	public function setOptions( $name, $value ) {
		if ( is_array($name) ) {
			$this->options = array_merge($this->options, $name);
		}else {
			$this->options[$name] = $value;
		}
		return $this;
	}
	
	/**
	 * @param $name
	 * @param $value
	 * @return self
	 */
	public function __set($name, $value)
	{
		// TODO: Implement __set() method.
		if ( in_array( $name, self::optionList ) ) {
			$this->setOptions($name, $value);
		}
		return $this;
	}
	
	public function __get($name)
	{
		// TODO: Implement __get() method.
		return $this->{$name};
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}